package com.wingice.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wingice.exception.BusinessException;
import com.wingice.system.entity.SysDepartment;
import com.wingice.system.entity.SysUser;
import com.wingice.system.mapper.SysDepartmentMapper;
import com.wingice.system.service.SysDepartmentService;
import com.wingice.system.service.SysUserService;
import com.wingice.system.vo.SysDepartmentView;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门信息 服务实现类
 * </p>
 *
 * @author 胡昊
 * @since 2023-04-10
 */
@Service
public class SysDepartmentServiceImpl extends ServiceImpl<SysDepartmentMapper, SysDepartment> implements SysDepartmentService {

    @Resource
    private SysUserService sysUserService;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean insertSysDepartment(SysDepartment sysDepartment) {
        if (sysDepartment.getParentId().equals(sysDepartment.getId())) {
            throw new BusinessException("父部门不允许为自己");
        }
        return save(sysDepartment);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteBatch(List<String> idList) {
        final long subDepartmentNum = count(Wrappers.<SysDepartment>lambdaQuery().in(SysDepartment::getParentId, idList));
        if (subDepartmentNum > 0) {
            throw new BusinessException("包含子部门，不允许删除");
        }
        final long userNum = sysUserService.count(Wrappers.<SysUser>lambdaQuery().in(SysUser::getDepartmentId, idList));
        if (userNum > 0) {
            throw new BusinessException("部门包含用户，不允许删除");
        }
        return removeBatchByIds(idList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateSysDepartment(SysDepartment sysDepartment) {
        if (sysDepartment.getParentId().equals(sysDepartment.getId())) {
            throw new BusinessException("父部门不允许为自己");
        }
        final List<String> subDepartmentIdList = listSubDepartmentIdList(sysDepartment.getId());
        if (subDepartmentIdList.contains(sysDepartment.getParentId())) {
            throw new BusinessException("父部门不允许选择自己的子部门");
        }
        return updateById(sysDepartment);
    }

    @Transactional(readOnly = true)
    @Override
    public List<String> listSubDepartmentIdList(String departmentId) {
        final List<String> idList = new ArrayList<>();
        if (departmentId == null) {
            return idList;
        }
        final List<SysDepartment> companyList = list();
        getChildrenDepartment(idList, departmentId, companyList);
        return idList;
    }

    @Override
    public List<SysDepartmentView> treeSysDepartment() {
        final List<SysDepartmentView> result = new ArrayList<>();
        final List<SysDepartment> allSysDepartment = list();
        final List<SysDepartment> topSysDepartment = allSysDepartment
                .stream()
                .filter(sysDepartment -> sysDepartment.getParentId().equals("0"))
                .collect(Collectors.toList());
        topSysDepartment.forEach(sysDepartment -> {
            final SysDepartmentView sysDepartmentView = new SysDepartmentView();
            BeanUtil.copyProperties(sysDepartment, sysDepartmentView);
            getChildrenDepartmentView(result, sysDepartmentView, allSysDepartment);
        });
        return result;
    }

    private void getChildrenDepartmentView(List<SysDepartmentView> result, SysDepartmentView sysDepartmentView, List<SysDepartment> allSysDepartment) {
        result.add(sysDepartmentView);
        allSysDepartment.stream()
                .filter(sysDepartment -> sysDepartment.getParentId().equals(sysDepartment.getId()))
                .forEach(sysDepartment -> {
                    final SysDepartmentView item = new SysDepartmentView();
                    BeanUtil.copyProperties(sysDepartment, item);
                    getChildrenDepartmentView(result, item, allSysDepartment);
                });
    }

    private void getChildrenDepartment(List<String> idList, String departmentId, List<SysDepartment> sysDepartmentList) {
        idList.add(departmentId);
        sysDepartmentList.stream()
                .filter(company -> company.getParentId().equals(departmentId))
                .forEach(company -> getChildrenDepartment(idList, company.getId(), sysDepartmentList));
    }


}
